// 发布订阅 --观察者模式 定义了对象之间一对多的关系。让多个观察者对象同时监听一个主题对象，
// 当这个主题对象发生改变（发布）时，所有订阅（观察者订阅）将都的到通知
// 观察者就是订阅者，观察者有多个，发布者只有一个
// 生活例子：卖家是发布者起发布消息作用。，买家是观察者
/*
1.首先确定好谁是发布者
2.确定好发布者后，给发布者一个缓存列表，用于存放回调函数来通知订阅者（观察者）
3.最后是发布消息，发布者遍历这个缓存列表，依次触发缓存列表订阅者（观察者）回调函数。

*/

// let shoeObj = {}
// shoeObj.list = []
// // 增加订阅者
// shoeObj.listen = function (fn) {//fn就是订阅消息
//   // console.log(this)
//   shoeObj.list.push(fn) //一个订阅者（观察者）订阅一条消息。把此消息加入到缓存列表中
// }
// // 发布消息
// shoeObj.trigger = function (...rest) {
//   // console.log(this)
//   for (var i = 0, fn; fn = this.list[i++];) {
//     //fn就是订阅listen传的回调函数 rest就是用户trigger传的实参
//     fn.apply(this, rest)//实参列表 

//   }
// }
// // A订阅消息
// shoeObj.listen(function (color, size) {
//   console.log(color)
//   console.log(size)
// })

// // B订阅消息
// shoeObj.listen(function(color,size){
//   // console.log(this)
//   console.log(`B${color}`)
//   console.log(`B${size}`)
// })

// shoeObj.trigger('红色', 40) //trigger会把所有的list回调函数触发 （每个订阅者都会接收到发布者的每个消息）
// // 改进加入一key 让每个订阅者只订阅自己的消息
// shoeObj.trigger('黑色', 42)

// for (let i = 0; i < 10; i++) {

// }

// let shoeObj = {
//   list: [],
//   listen(fn) {
//     this.list.push(fn)
//   },
//   trigger(...rest) {
//     for (let i = 0; i < this.list.length; i++) {
//       let fn = this.list[i]
//       fn.apply(this, rest)
//     }
//   }
// }
// // A订阅消息
// shoeObj.listen(function (color, size) {
//   console.log(`A${color}`)
//   console.log(`A${size}`)

// })
// // B订阅消息
// shoeObj.listen(function (color, size) {
//   console.log(`B${color}`)
//   console.log(`B${size}`)

// })
// 发布者发布消息
// shoeObj.trigger('red', 40)
// shoeObj.trigger('black', 42)
/*
Ared
A40
Bred
B40
Ablack
A42
Bblack
B42
每个订阅者（观察者）都会接收到发布者发布的每个信息
问题是：对于A来说只想接收shoeObj.trigger('red', 40)。不想接受到shoeObj.trigger('black', 42)消息。
就是说让每个订阅者只收到自己订阅的消息
*/
// 版本2，让每个订阅者只接收到自己订阅的消息
// let shoeObj1 = {
//   list: [],
//   listen(type, fn) {
//     // 如果还没有订阅此消息，就给该消息一个缓存列表
//     if (!this.list[type]) {
//       this.list[type] = []
//     }
//     this.list.push(fn)

//   },
//   trigger(type, ...rest) {
//     let fns = this.list[type]
//     console.log(fns)
//     if (!fns || fns.length == 0) {
//       return
//     }
//     for (let i = 0; i < fns.length; i++) {
//       let fn = fns[i]
//       console.log(rest)
//       fn.apply(this, rest)
//     }
//   }
// }
// // A订阅
// shoeObj1.listen('red', function (size) {
//   console.log(`A${size}`)
// })
// // B订阅
// shoeObj1.listen('black', function (size) {
//   console.log(`B${size}`)
// })
// shoeObj1.trigger('red',40)
// shoeObj1.trigger('black',42)

var shoeObj = {}; // 定义发布者
shoeObj.list = []; // 缓存列表 存放订阅者回调函数 [ red: [ [Function] ], block: [ [Function] ] ]

// 增加订阅者
shoeObj.listen = function (key, fn) {
  console.log(this.list)
  console.log(this.list[key])
  if (!this.list[key]) {
    // 如果还没有订阅过此类消息，给该类消息创建一个缓存列表
    this.list[key] = [];
    console.log(this.list[key])

  }
  this.list[key].push(fn);  // 订阅消息添加到缓存列表
  console.log( this.list[key] instanceof Array)
}

// 发布消息
shoeObj.trigger = function () {
  // console.log(arguments) [Arguments] { '0': 'red', '1': 40 }
  var key = Array.prototype.shift.call(arguments); // 取出消息类型名称
  // console.log(key ,arguments) [Arguments] { '0': 40 }
  var fns = this.list[key];  // 取出该消息对应的回调函数的集合

  // 如果没有订阅过该消息的话，则返回
  if (!fns || fns.length === 0) {
    return;
  }
  for (var i = 0, fn; fn = fns[i++];) {
    fn.apply(this, arguments); // arguments 是发布消息时附送的参数
  }
};

// 小红订阅如下消息
shoeObj.listen('red', function (size) {
  console.log("尺码是：" + size);
});

// 小花订阅如下消息
shoeObj.listen('block', function (size) {
  console.log("再次打印尺码是：" + size);
});
shoeObj.trigger("red", 40);
shoeObj.trigger("red", 40);
shoeObj.trigger("block", 42);